home *** CD-ROM | disk | FTP | other *** search
/ Power CD-ROM!! 8 / Power CD-ROM 8.iso / prgmming / maxlib10 / pbfiles / pbfiles.asm next >
Encoding:
Assembly Source File  |  1994-10-14  |  45.2 KB  |  1,322 lines

  1. comment|          PBFILES.ASM  for PowerBASIC 3.0b or later.
  2.  
  3.    Written by Brian McLaughlin. Released into public domain.
  4.  
  5.    DECLARE FUNCTION OpenF% (FileSpec$)
  6.    DECLARE SUB CloseF (Handle%)
  7.    DECLARE SUB GetF (Handle%, Bytes&, ToVariable AS ANY)
  8.    DECLARE SUB PutF (Handle%, Bytes&, FromVariable AS ANY)
  9.    DECLARE SUB GetStF (Handle%, ToStrng AS ANY)
  10.    DECLARE SUB PutStF (Handle%, FromStrng AS ANY)
  11.    DECLARE SUB LoadF (Handle%, Bytes&, ToSegment??)
  12.    DECLARE SUB SaveF (Handle%, Bytes&, FromSegment??)
  13.    DECLARE FUNCTION GetLineF$ (Handle%)
  14.    DECLARE FUNCTION EndF% ()
  15.    DECLARE SUB SaveLineF ()
  16.    DECLARE FUNCTION SizeF& (Handle%)
  17.    DECLARE FUNCTION GetLocF& (Handle%)
  18.    DECLARE SUB SetLocF (Handle%, NewPtrLoc&)
  19.    DECLARE SUB ClipF (Handle%, NewSize&)
  20.    DECLARE SUB FlushF (Handle%)
  21.    DECLARE SUB KillF (FileSpec$)
  22.    DECLARE FUNCTION ErrorCode% ()
  23.    DECLARE SUB SetErrorCode (ErrorCode%)
  24.    DECLARE SUB SetBufferSize (Bytes%)
  25.    DECLARE SUB SetPtrBase (PtrBase%)
  26.    DECLARE FUNCTION GetPtrBase% ()
  27.    DECLARE FUNCTION HandleF% ()
  28.    DECLARE SUB SetAccessCode (AccessCode%)
  29.  
  30. end comment|
  31.  
  32.  
  33. Code Segment Byte
  34.      Assume  CS:Code
  35.  
  36.      Extrn   GETSTRLOC:FAR
  37.      Extrn   GETSTRALLOC:FAR
  38.      Extrn   RLSSTRALLOC:FAR
  39.  
  40.      LineHandle   DW 0FFFFh ; set initial handle to -1
  41.      BufHandle    DW 0      ; handle of buffer string used by GetLineF
  42.      ReturnHandle DW 0      ; handle of string returned by GetLineF
  43.      BufSeg       DW 0      ; segment allocated to the buffer
  44.      BufOfs       DW 0      ; offset allocated to the buffer
  45.      BufSize      DW 1FEEh  ; sets initial buffer size at 8174 bytes
  46.      BufFilled    DW 0      ; number of bytes read into buffer most recently
  47.      BufIndex     DW 0      ; index to byte in buffer where scan starts
  48.      RemainsLow   DW 0      ; number of bytes remaining to be read into buffer
  49.      RemainsHigh  DW 0
  50.      LinePtrLow   DW 0      ; used by GetLineF as internal pointer
  51.      LinePtrHigh  DW 0
  52.      LineError    DW 0      ; flags when GetLineF was interrupted by error
  53.      FileEnd      DW 0      ; set by GetLineF, reported by EndF
  54.      CreatedFile  DW 0      ; used in OpenF
  55.  
  56.      Old24Segment DW 0      ; used by $CritInstall, $CritRemove
  57.      Old24Offset  DW 0      ; used by $CritInstall, $CritRemove
  58.      LowWord      DW 0      ; scratch variables
  59.      HighWord     DW 0
  60.      Error        DW 0      ; internal error code variable
  61.      CritErrCode  DW 0      ; used by $CritHandler, $CritCheck
  62.      LastHandle   DW 0      ; most recent handle opened by OpenF
  63.      PtrBase      DW 0      ; pointer base (initialize to zero)
  64.      AccessCode   DB 2           ; preset for read/write, compatibility mode
  65.      StrData      DB 65 DUP(0)   ; holds ASCIIZ filenames
  66.  
  67.  
  68. PUBLIC OpenF, CloseF, FlushF, GetF, PutF, GetStF, PutStF, LoadF, SaveF
  69. PUBLIC SetLocF, GetLocF, SizeF, KillF,  HandleF, SetErrorCode, ClipF
  70. PUBLIC SetBufferSize, GetLineF, EndF, SetAccessCode, SetPtrBase, GetPtrBase
  71. PUBLIC SaveLineF, ErrorCode
  72.  
  73.  
  74.  
  75. comment |************************************************************
  76. *
  77. *   Name:               ErrorCode
  78. *
  79. *   Type:               FUNCTION
  80. *   Parameters:         none
  81. *   Values returned:    value of internal Error variable
  82. *
  83. *********************************************************************|
  84.  
  85. ErrorCode PROC FAR          ; returns most recent error code
  86.     Mov AX, CS:Error
  87.     Retf
  88. ErrorCode ENDP
  89.  
  90.  
  91. comment |************************************************************
  92. *
  93. *   Name:               SetErrorCode
  94. *
  95. *   Type:               SUB
  96. *   Parameters:         AccessCode%     (access at [BP+6])
  97. *   Values returned:    none
  98. *
  99. *********************************************************************|
  100.  
  101. SetErrorCode PROC FAR    ; resets value of error code variable
  102.     Push BP
  103.     Mov BP, SP
  104.     Les BX, [BP+6]
  105.     Mov AX, ES:[BX]      ; AX = new error code
  106.     Mov CS:Error, AX     ; reset Error to new value
  107.     Pop BP
  108.     Retf 4
  109. SetErrorCode ENDP
  110.  
  111.  
  112. comment |************************************************************
  113. *
  114. *   Name:               SetAccessCode
  115. *
  116. *   Type:               SUB
  117. *   Parameters:         AccessCode%     (access at [BP+6])
  118. *   Values returned:    none
  119. *
  120. *********************************************************************|
  121.  
  122. SetAccessCode PROC FAR   ; lets programmer set file access code
  123.     Push BP
  124.     Mov BP, SP
  125.     Les BX, [BP+6]
  126.     Mov AX, ES:[BX]      ; AX = new access code (as integer)
  127.     Mov CS:AccessCode, AL; set AccessCode to new value (low byte only)
  128.     Pop BP
  129.     Retf 4
  130. SetAccessCode ENDP
  131.  
  132.  
  133. comment |************************************************************
  134. *
  135. *   Name:               SetPtrBase
  136. *
  137. *   Type:               SUB
  138. *   Parameters:         Switch%     (access at [BP+6])
  139. *   Values returned:    none
  140. *
  141. *********************************************************************|
  142.  
  143. SetPtrBase PROC FAR     ; resets pointer base value to 1 or zero
  144.     Push BP
  145.     Mov BP, SP
  146.     Mov CS:PtrBase, 0   ; assume base of zero
  147.     Les BX, [BP+6]      ; point ES:BX to PtrBase%
  148.     Mov CX, ES:[BX]
  149.     Jcxz BaseSet
  150.     Mov CS:PtrBase, 1
  151. BaseSet:
  152.     Pop BP
  153.     Retf 4
  154. SetPtrBase ENDP
  155.  
  156.  
  157. comment |************************************************************
  158. *
  159. *   Name:               GetPtrBase
  160. *
  161. *   Type:               FUNCTION
  162. *   Parameters:         none
  163. *   Values returned:    value of internal PtrBase variable
  164. *
  165. *********************************************************************|
  166.  
  167. GetPtrBase PROC FAR     ; returns pointer base value
  168.     Mov AX, CS:PtrBase
  169.     Retf
  170. GetPtrBase ENDP
  171.  
  172.  
  173. comment |************************************************************
  174. *
  175. *   Name:               HandleF
  176. *
  177. *   Type:               FUNCTION
  178. *   Parameters:         none
  179. *   Values returned:    handle of last file opened by OpenF
  180. *
  181. *********************************************************************|
  182.  
  183. HandleF PROC FAR        ; returns handle of last file opened with OpenF
  184.     Mov AX, CS:LastHandle
  185.     Retf
  186. HandleF ENDP
  187.  
  188.  
  189. comment |************************************************************
  190. *
  191. *   Name:               EndF
  192. *
  193. *   Type:               FUNCTION
  194. *   Parameters:         none
  195. *   Values returned:    value of internal FileEnd variable
  196. *
  197. *********************************************************************|
  198.  
  199. EndF PROC FAR          ; returns value of CS:FileEnd, as set by GetLineF
  200.     Mov AX, CS:FileEnd
  201.     Retf
  202. EndF ENDP
  203.  
  204.  
  205. comment |************************************************************
  206. *
  207. *   Name:               SaveLineF
  208. *
  209. *   Type:               SUB
  210. *   Parameters:         none
  211. *   Values returned:    none
  212. *
  213. *********************************************************************|
  214.  
  215. SaveLineF PROC FAR     ; resets DOS file pointer to agree with GetLineF
  216.     Call $ResetLinePtr
  217. SaveLineF ENDP
  218.  
  219.  
  220. comment |************************************************************
  221. *
  222. *   Name:               SetBufferSize
  223. *
  224. *   Type:               SUB
  225. *   Parameters:         BufferSize%     (access at [BP+6])
  226. *   Values returned:    none
  227. *
  228. *********************************************************************|
  229.  
  230. SetBufferSize PROC FAR
  231.     Push BP
  232.     Mov BP, SP
  233.     Les BX, [BP+6]
  234.     Mov AX, ES:[BX]        ;AX = Bytes%
  235.     Cmp AX, 1006           ;see if Bytes% is less than 1006 bytes
  236.     Jl  AdjustUp           ; if so, go adjust it up to 1006 bytes
  237.     Cmp AX, 32750
  238.     Jg  AdjustDown
  239. SetSize:
  240.     Mov CS:BufSize, AX     ; save it
  241. SetExit:
  242.     Pop BP
  243.     Retf 4
  244. AdjustUp:
  245.     Mov AX, 1006           ;don't allow buffer size < 1006 bytes
  246.     Jmp SHORT SetSize
  247. AdjustDown:
  248.     Mov AX, 32750          ;don't allow buffer size > 32750 bytes
  249.     Jmp SHORT SetSize
  250. SetBufferSize ENDP
  251.  
  252.  
  253. comment |************************************************************
  254. *
  255. *   Name:               OpenF
  256. *
  257. *   Type:               FUNCTION
  258. *   Parameters:         FileName$     (access at [BP+6])
  259. *   Values returned:    DOS handle for opened file
  260. *
  261. *********************************************************************|
  262.  
  263. OpenF PROC FAR           ; access FileName$ at [BP+6]
  264.     Push BP
  265.     Mov BP, SP
  266.     Push SI
  267.     Push DI
  268.     Push DS
  269.     Call $CritInstall
  270.     Mov CS:CreatedFile, 0 ; assume the file FileName$ already exists
  271.     Lds BX, [BP+6]       ; DS:BX = address of FileName$ handle
  272.     Mov AX, [BX]         ; AX = handle of filename
  273.     Push AX              ; leave handle on stack for GETSTRLOC
  274.     Call GETSTRLOC       ; this puts address in DX:AX, length in CX
  275.     Jcxz BadName         ; oops! no name of a file to open
  276.     Cmp CX, 64           ; see if FileName$ + CHR$(0) will fit in StrData
  277.     Ja  BadName          ; if not, we can't process it
  278.     Mov DS, DX
  279.     Mov SI, AX           ;DS:SI point to first byte of filename
  280.     Push CS
  281.     Pop ES               ; point ES at code seg, where StrData resides
  282.     Mov DI, Offset StrData   ;ES:DI points to start of StrData
  283.     Rep Movsb            ; put a copy of name in StrData
  284.     Mov ES:[DI], CL      ; put a zero char at end of filename in StrData
  285. OpenFile:
  286.     Mov AH, 3Dh          ; we'll try to open the file with DOS service 3Dh
  287.     Mov AL, AccessCode   ; put access code we'll use into AL
  288.     Push CS
  289.     Pop DS                  ; set DS = CS
  290. CreateFile:                 ; CX = 0 = normal file attribute (if creating)
  291.     Mov DX, Offset StrData  ;DS:DX points to ASCIIZ filename in CS:StrData
  292.     Int 21h                 ; call DOS to either open or create FileName$
  293.     Call $CritCheck         ; check for errors
  294.     Jc OpenError            ; if no error AX = file handle
  295.     Cmp CS:CreatedFile, 0   ; see if the file we opened was just created
  296.     Jne CloseNewFile        ; if it was, we need to close it and reopen it
  297.     Mov CS:LastHandle, AX   ; otherwise, save a copy of the handle
  298. OpenExit:                   ; and exit
  299.     Call $CritRemove
  300.     Pop DS
  301.     Pop DI
  302.     Pop SI
  303.     Pop BP
  304.     Retf 4
  305. OpenError:
  306.     Cmp AX, 2            ; was it a "file not found" error (2)?
  307.     Jne RealError        ; was a different error than "file not found"
  308.     Mov AX, 3C00h        ; otherwise, call DOS service to create file
  309.     Mov CS:CreatedFile, -1  ;flag that we are creating a new file
  310.     Jmp SHORT CreateFile ; go back and create the file FileName$
  311. BadName:
  312.     Mov AX, 2            ; if FileName$ unusable return "file not found"
  313. RealError:
  314.     Mov CS:Error, AX     ; dump error code into Error
  315.     Xor AX, AX           ; put 0 where handle expected
  316.     Jmp SHORT OpenExit   ; return
  317. CloseNewFile:
  318.     Mov BX, AX           ; put the new file's handle in BX
  319.     Mov AX, 3E00h        ; close the newly created file
  320.     Int 21h
  321.     Call $CritCheck
  322.     Jc  RealError
  323.     Mov CS:CreatedFile, 0  ; now flag that the file is ALREADY created
  324.     Jmp SHORT OpenFile     ; and re-open it with proper access code
  325. OpenF ENDP
  326.  
  327.  
  328. comment |************************************************************
  329. *
  330. *   Name:               CloseF
  331. *
  332. *   Type:               SUB
  333. *   Parameters:         Handle%     (access at [BP+6])
  334. *   Values returned:    none
  335. *
  336. *********************************************************************|
  337.  
  338. CloseF PROC FAR          ; access Handle% at [BP+6]
  339.     Push BP
  340.     Mov BP, SP
  341.     Call $CritInstall
  342.     Les BX, [BP+6]       ; ES:BX point to Handle%
  343.     Mov BX, ES:[BX]      ; BX = Handle%
  344.     Cmp BX, 5            ; don't close the DOS reserved handles (0-4)
  345.     Jb  CloseExit        ; just quietly do nothing and exit
  346.     Cmp BX, CS:LineHandle  ; see if this handle is last one read by GetLineF
  347.     Je  ResetLineHandle    ; if it is, reset the CS:LineHandle variable
  348. ResumeClose:
  349.     Mov AX, 3E00h        ; DOS close file service
  350.     Int 21h
  351.     Call $CritCheck
  352.     Jc CloseError
  353. CloseExit:
  354.     Call $CritRemove
  355.     Pop BP
  356.     Retf 4
  357. CloseError:
  358.     Mov CS:Error, AX
  359.     Jmp SHORT CloseExit
  360. ResetLineHandle:
  361.     Mov CS:LineHandle, 0FFFFh
  362.     Jmp SHORT ResumeClose
  363. CloseF ENDP
  364.  
  365.  
  366. comment |************************************************************
  367. *
  368. *   Name:               FlushF
  369. *
  370. *   Type:               SUB
  371. *   Parameters:         Handle%     (access at [BP+6])
  372. *   Values returned:    none
  373. *
  374. *********************************************************************|
  375.  
  376. FlushF PROC FAR          ; access Handle% at [BP+6]
  377.     Push BP
  378.     Mov BP, SP
  379.     Call $CritInstall
  380.     Les BX, [BP+6]
  381.     Mov BX, ES:[BX]      ; BX = Handle%
  382.     Mov AH, 45h          ; AH = service 45h of DOS
  383.     Int 21h              ; opens a duplicate handle for a file
  384.     Call $CritCheck      ; and returns it in AX
  385.     Jc  FlushError
  386.     Mov BX, AX           ;BX = dupe handle returned by DOS
  387.     Mov AH, 3Eh          ; now call close handle service
  388.     Int 21h              ; to close the duplicate handle,
  389.     Call $CritCheck      ; which flushes DOS buffers to disk,
  390.     Jc  FlushError       ; without closing the original handle
  391. FlushExit:
  392.     Call $CritRemove
  393.     Pop BP
  394.     Retf 4
  395. FlushError:
  396.     Mov CS:Error, AX
  397.     Jmp SHORT FlushExit
  398. FlushF ENDP
  399.  
  400.  
  401. comment |************************************************************
  402. *
  403. *   Name:               GetF
  404. *
  405. *   Type:               SUB
  406. *   Parameters:         Handle%     (access at [BP+14])
  407. *                       Bytes&      (access at [BP+10])
  408. *                       ToVariable  (access at [BP+6])
  409. *   Values returned:    none
  410. *
  411. *********************************************************************|
  412.  
  413. GetF PROC FAR
  414.     Push BP
  415.     Mov BP, SP
  416.     Call $CritInstall
  417.     Push DS
  418.     Push SI
  419.     Lds BX, [BP+10]      ; DS:BX points to Bytes&
  420.     Mov AX, [BX]         ; put Bytes& into DX:AX
  421.     Mov DX, [BX+2]
  422.     Cmp DX, 0            ; see if we are dealing with a negative Bytes&
  423.     Jl  ReadExit
  424.     Or  AX, AX
  425.     Jnz GetBytesNotZero
  426.     Or  DX, DX
  427.     Jz  ReadExit
  428. GetBytesNotZero:
  429.     Lds BX, [BP+14]      ; DS:BX points to Handle%
  430.     Mov BX, [BX]         ; Handle% in BX
  431.     Mov CX, AX           ; CX = low byte of Bytes&
  432.     And CX, 7FFFh        ; CX = any remainder < 32K bytes
  433.     Push CX              ; save that value for later
  434.     Mov CX, 15           ; loop counter for Shr loop
  435. Top:
  436.     Shr DX, 1
  437.     Rcr AX, 1
  438.     Loop Top             ; divides DX:AX by 32K
  439.     Lds DX, [BP+6]       ; load DS:DX with address to read file into
  440.     Mov CX, AX           ;CX = result of Bytes& \ 32K
  441.     Jcxz LessThan32K     ; if zero then LOF was < 32K
  442. Top2:
  443.     Push CX              ; save loop counter
  444.     Mov CX, 8000h        ; CX = 32K bytes to copy
  445.     Mov AX, 3F00h        ; DOS read from file service
  446.     Int 21h              ; BX still contains Handle% still
  447.     Call $CritCheck      ;
  448.     Jc ReadError         ; must clean up stack, if error occurs here
  449.     Mov CX, DS           ; we need to adjust segment upward
  450.     Add CX, 2048         ; 2K paragraphs = 32K bytes
  451.     Mov DS, CX           ; DS now points to proper segment
  452.     Pop CX               ; resume loop counter
  453.     Loop Top2
  454. LessThan32K:
  455.     Pop CX               ; this puts remainder into CX
  456.     Mov AX, 3F00h        ; DOS "read from file" service
  457.     Int 21h
  458.     Call $CritCheck
  459.     Jc ReadError2        ; stack has no extra pushes on it
  460. ReadExit:
  461.     Pop SI
  462.     Pop DS
  463.     Call $CritRemove
  464.     Pop BP
  465.     Retf 12              ; remove three parameters
  466. ReadError:
  467.     Add SP, 4            ; remove the residue of two pushes
  468. ReadError2:
  469.     Mov CS:Error, AX     ; leave error code for ErrorCode% to find
  470.     Jmp SHORT ReadExit
  471. GetF ENDP
  472.  
  473.  
  474. comment |************************************************************
  475. *
  476. *   Name:               PutF
  477. *
  478. *   Type:               SUB
  479. *   Parameters:         Handle%      (access at [BP+14])
  480. *                       Bytes&       (access at [BP+10])
  481. *                       FromVariable (access at [BP+6])
  482. *   Values returned:    none
  483. *
  484. *********************************************************************|
  485.  
  486. PutF PROC FAR
  487.     Push BP
  488.     Mov BP, SP
  489.     Call $CritInstall
  490.     Push DS
  491.     Push SI
  492.     Lds BX, [BP+14]      ; DS:BX = address of Handle%
  493.     Mov BX, [BX]         ;BX = handle of file to write to
  494.     Lds SI, [BP+10]      ; DS:SI = address of Bytes&
  495.     Mov AX, [SI]         ;AX = low word of Bytes&
  496.     Mov DX, [SI+2]       ;DX:AX = Bytes&
  497.     Cmp DX, 0            ; see if we are dealing with a negative Bytes&
  498.     Jl  WriteExit        ; if so, exit
  499.     Or  AX, AX           ; see if Bytes& = 0
  500.     Jnz PutBytesNotZero
  501.     Or  DX, DX
  502.     Jz  WriteExit        ; if Bytes& = 0, then exit
  503. PutBytesNotZero:
  504.     Mov CX, AX           ;CX = low word of Bytes&
  505.     And CX, 7FFFh        ; CX = any remainder < 32K
  506.     Push CX              ; save it for later
  507.     Mov CX, 15           ; loop counter
  508. LoopTop:
  509.     Shr DX, 1            ; shift-divide DX:AX by 32K
  510.     Rcr AX, 1
  511.     Loop LoopTop
  512.     Lds DX, [BP+6]       ; DS:DX points to memory block to write to disk
  513.     Mov CX, AX           ; CX = number of 32K blocks to write to disk
  514.     Or  AX, AX           ; was Bytes& >= 32K?
  515.     Jnz LoopTop2         ; if so, jump to take care of it
  516. NotOver32K:
  517.     Pop CX               ; this puts remainder into CX
  518.     Mov AX, 4000h        ; DOS write to file service
  519.     Int 21h
  520.     Call $CritCheck
  521.     Jc WriteError2       ; stack has no extra pushes
  522. WriteExit:
  523.     Pop SI
  524.     Pop DS
  525.     Call $CritRemove
  526.     Pop BP
  527.     Retf 12
  528. WriteError:
  529.     Add SP, 4            ; remove the residue of two pushes
  530. WriteError2:
  531.     Mov CS:Error, AX
  532.     Jmp SHORT WriteExit  ; leave error code for ErrorCode% to find
  533. LoopTop2:
  534.     Push CX              ; save loop counter
  535.     Mov CX, 8000h        ; CX = 32K bytes to copy
  536.     Mov AX, 4000h        ; DOS write to file service
  537.     Int 21h              ; BX still contains Handle%
  538.     Call $CritCheck      ;
  539.     Jc WriteError        ; stack must be cleaned up, if error here
  540.     Mov CX, DS           ; we need to adjust segment upward
  541.     Add CX, 2048         ; 2K paragraphs = 32K bytes
  542.     Mov DS, CX           ;
  543.     Pop CX               ; restore loop counter
  544.     Loop LoopTop2
  545.     Jmp SHORT NotOver32K
  546. PutF ENDP
  547.  
  548.  
  549. comment |************************************************************
  550. *
  551. *   Name:               GetStF
  552. *
  553. *   Type:               SUB
  554. *   Parameters:         Handle%     (access at [BP+10])
  555. *                       ToString    (access at [BP+6])
  556. *   Values returned:    none
  557. *
  558. *********************************************************************|
  559.  
  560. GetStF PROC FAR
  561.     Push BP
  562.     Mov BP, SP
  563.     Les AX, [BP+10]      ; ES:AX points to Handle%
  564.     Push ES
  565.     Push AX              ; push both segment and offset for GetF
  566.     Les BX, [BP+6]       ; ES:BX = address of string-handle for ToStrng
  567.     Mov AX, ES:[BX]      ; AX = handle of string
  568.     Push AX
  569.     Call GETSTRLOC       ; puts seg:off in DX:AX, length into CX
  570.     Mov CS:HighWord, 0   ; zero the high word variable, so we can ...
  571.     Mov CS:LowWord, CX   ; send length of ToStrng to GetF as Bytes&
  572.     Mov BX, Offset LowWord  ; and push a pointer to it onto stack
  573.     Push CS              ; CS:BX points to highword/lowword of "Bytes&"
  574.     Push BX              ; and DX:AX point to ToStrng
  575.     Push DX              ; push 'em both as a ToVariable for GetF
  576.     Push AX
  577.     Call FAR PTR GetF    ; make it a far call
  578.     Pop BP
  579.     Retf 8
  580. GetStF ENDP
  581.  
  582.  
  583. comment |************************************************************
  584. *
  585. *   Name:               PutStF
  586. *
  587. *   Type:               SUB
  588. *   Parameters:         Handle%       (access at [BP+10])
  589. *                       FromString    (access at [BP+6])
  590. *   Values returned:    none
  591. *
  592. *********************************************************************|
  593.  
  594. PutStF PROC FAR          ; access Handle% at [BP+10]
  595.     Push BP              ;      FromStrng at [BP+6]
  596.     Mov BP, SP
  597.     Les AX, [BP+10]      ; ES:AX points to Handle%
  598.     Push ES
  599.     Push AX              ; push both segment and offset for GetF
  600.     Les BX, [BP+6]       ; ES:BX = address of string-handle for FromStrng
  601.     Mov AX, ES:[BX]      ; AX = handle of string
  602.     Push AX
  603.     Call GETSTRLOC       ; puts seg:off in DX:AX, length into CX
  604.     Mov CS:HighWord, 0   ; zero the high word variable, so we can ...
  605.     Mov CS:LowWord, CX   ; send length of FromStrng to GetF as Bytes&
  606.     Mov BX, Offset LowWord  ; and push a pointer to it onto stack
  607.     Push CS              ; CS:BX points to highword/lowword of "Bytes&"
  608.     Push BX              ; and DX:AX point to FromStrng
  609.     Push DX              ; push 'em both as a FromVariable for GetF
  610.     Push AX
  611.     Call FAR PTR PutF    ; make it a far call
  612.     Pop BP
  613.     Retf 8
  614. PutStF ENDP
  615.  
  616.  
  617. comment |************************************************************
  618. *
  619. *   Name:               SaveF
  620. *
  621. *   Type:               SUB
  622. *   Parameters:         Handle%          (access at [BP+14])
  623. *                       Bytes&           (access at [BP+10])
  624. *                       FromSegment??    (access at [BP+6])
  625. *   Values returned:    none
  626. *
  627. *********************************************************************|
  628.  
  629. SaveF PROC NEAR
  630.     Push BP
  631.     Mov BP, SP
  632.     Les AX, [BP+14]
  633.     Push ES              ;push address of Handle%
  634.     Push AX
  635.     Les AX, [BP+10]
  636.     Push ES              ;push address of Bytes&
  637.     Push AX
  638.     Les BX, [BP+6]
  639.     Mov AX, ES:[BX]
  640.     Push AX              ;push value of FromSegment??
  641.     Xor AX, AX           ;assume offset of 0
  642.     Push AX              ;push value of offset
  643.     Call FAR PTR PutF
  644.     Pop BP
  645.     Retf 12
  646. SaveF ENDP
  647.  
  648.  
  649. comment |************************************************************
  650. *
  651. *   Name:               LoadF
  652. *
  653. *   Type:               SUB
  654. *   Parameters:         Handle%        (access at [BP+14])
  655. *                       Bytes&         (access at [BP+10])
  656. *                       ToSegment??    (access at [BP+6])
  657. *   Values returned:    none
  658. *
  659. *********************************************************************|
  660.  
  661. LoadF PROC NEAR
  662.     Push BP
  663.     Mov BP, SP
  664.     Les AX, [BP+14]
  665.     Push ES              ;push address of Handle%
  666.     Push AX
  667.     Les AX, [BP+10]
  668.     Push ES              ;push address of Bytes&
  669.     Push AX
  670.     Les BX, [BP+6]
  671.     Mov AX, ES:[BX]
  672.     Push AX              ;push value of ToSegment??
  673.     Xor AX, AX           ;assumes offset of 0
  674.     Push AX              ;push value of offset
  675.     Call FAR PTR GetF
  676.     Pop BP
  677.     Retf 12
  678. LoadF ENDP
  679.  
  680.  
  681. comment |************************************************************
  682. *
  683. *   Name:               SetLocF
  684. *
  685. *   Type:               SUB
  686. *   Parameters:         Handle%       (access at [BP+10])
  687. *                       NewPtrLoc&    (access at [BP+6])
  688. *   Values returned:    none
  689. *
  690. *********************************************************************|
  691.  
  692. SetLocF PROC FAR         ;access Handle% at [BP+10]
  693.     Push BP              ;    NewPtrLoc& at [BP+6]
  694.     Mov BP, SP
  695.     Call $CritInstall
  696.     Les BX, [BP+6]       ; load address of NewPtrLoc&
  697.     Mov DX, ES:[BX]      ; low word of NewPtrLoc& into DX
  698.     Mov CX, ES:[BX+2]    ; high word of NewPtrLoc& into CX
  699.     Sub DX, CS:PtrBase   ; PtrBase could be 1 or 0
  700.     Sbb CX, 0            ; so, adjust for current pointer base
  701.     Les BX, [BP+10]      ; load the address of Handle%
  702.     Mov BX, ES:[BX]      ; BX = Handle%
  703.     Mov AX, 4200h        ; we're moving from start of file
  704.     Int 21h              ; call DOS
  705.     Call $CritCheck      ; look for critical errors
  706.     Jc  SetLocError      ; if carry set, there was an error
  707. SetLocExit:
  708.     Call $CritRemove
  709.     Pop BP
  710.     Retf 8
  711. SetLocError:
  712.     Mov CS:Error, AX
  713.     Jmp SHORT SetLocExit
  714. SetLocF ENDP
  715.  
  716.  
  717. comment |************************************************************
  718. *
  719. *   Name:               GetLocF
  720. *
  721. *   Type:               FUNCTION
  722. *   Parameters:         Handle%       (access at [BP+6])
  723. *   Values returned:    current location of pointer in file: Handle%
  724. *
  725. *********************************************************************|
  726.  
  727. GetLocF PROC FAR
  728.     Push BP
  729.     Mov BP, SP
  730.     Push DS
  731.     Call $CritInstall
  732.     Lds BX, [BP+6]       ; address of Handle%
  733.     Mov BX, [BX]         ; BX = Handle%
  734.     Xor DX, DX
  735.     Xor CX, CX           ; tell DOS we'll be moving zero bytes
  736.     Mov AX, 4201h        ; from the present file position
  737.     Int 21h
  738.     Call $CritCheck
  739.     Jc  GetLocError      ; if no error DX:AX contains location
  740.     Add AX, CS:PtrBase   ; adjust location to fit current pointer base
  741.     Adc DX, 0            ; before returning
  742. GetLocExit:
  743.     Call $CritRemove
  744.     Pop DS
  745.     Pop BP
  746.     Retf 4
  747. GetLocError:
  748.     Mov CS:Error, AX     ; put AX into Error for ErrorCode%
  749.     Xor AX, AX           ; put a file location of 0
  750.     Xor DX, DX           ; into DX:AX
  751.     Jmp SHORT GetLocExit
  752. GetLocF ENDP
  753.  
  754.  
  755. comment |************************************************************
  756. *
  757. *   Name:               SizeF
  758. *
  759. *   Type:               FUNCTION
  760. *   Parameters:         Handle%       (access at [BP+6])
  761. *   Values returned:    current size of file: Handle%
  762. *
  763. *********************************************************************|
  764.  
  765. SizeF PROC FAR
  766.     Push BP
  767.     Mov BP, SP
  768.     Call $CritInstall
  769.     Les BX, [BP+6]       ; get address of Handle from stack
  770.     Mov BX, ES:[BX]      ; put Handle in BX
  771.     Xor CX, CX           ; CX:DX show how many bytes to move
  772.     Xor DX, DX           ; the file pointer during next call
  773.     Mov AX, 4201h        ; to DOS move-pointer service (42h)
  774.     Int 21h              ; we're moving it zero bytes this time
  775.     Call $CritCheck
  776.     Jc  SizeError
  777.     Mov CS:LowWord, AX   ; save current file pointer position
  778.     Mov CS:HighWord, DX  ; into memory for later
  779.     Xor DX, DX           ; Now we'll move zero bytes again, but
  780.     Xor CX, CX           ; this time to zero bytes from the EOF
  781.     Mov AX, 4202h        ; move pointer service (offset from end)
  782.     Int 21h              ; this operation points DX:AX at the last
  783.     Call $CritCheck      ; byte of file (as an offset from start)
  784.     Jc  SizeError
  785.     Xchg CS:LowWord, AX  ; now let's save it, and restore pointer
  786.     Xchg CS:HighWord, DX ; to the old position
  787.     Mov CX, DX           ; put the high byte into CX first
  788.     Mov DX, AX           ; and the low byte into DX
  789.     Mov AX, 4200h        ; this time move from the start of file!
  790.     Int 21h
  791.     Call $CritCheck
  792.     Jc  SizeError
  793.     Mov AX, CS:LowWord   ; put the LOF into DX:AX
  794.     Mov DX, CS:HighWord
  795. SizeExit:
  796.     Call $CritRemove     ; preserves state of carry flag
  797.     Pop BP
  798.     Ret 4
  799. SizeError:
  800.     Mov CS:Error, AX     ; put error code from AX into it
  801.     Xor AX, AX           ; put length of 0 into DX:AX
  802.     Xor DX, DX           ; which is better than a random value
  803.     Stc                  ; when ClipF calls, this flags the error
  804.     Jmp SHORT SizeExit   ; now return
  805. SizeF ENDP
  806.  
  807.  
  808. comment |************************************************************
  809. *
  810. *   Name:               ClipF
  811. *
  812. *   Type:               SUB
  813. *   Parameters:         Handle%       (access at [BP+10])
  814. *                       NewSize&      (access at [BP+6])
  815. *   Values returned:    none
  816. *
  817. *********************************************************************|
  818.  
  819. ClipF PROC FAR
  820.     Push BP
  821.     Mov BP, SP
  822.     Les AX, [BP+10]      ; ES:AX = address of Handle%
  823.     Push ES
  824.     Push AX              ; push the pointer back onto the stack for SizeF
  825.     Call FAR PTR SizeF   ; returns size in HighWord:LowWord and DX:AX
  826.     Jc  BareExit         ; if carry set, exit without calling $CritRemove
  827.     Call $CritInstall    ; this trashes DX:AX
  828.     Mov AX, CS:LowWord
  829.     Mov DX, CS:HighWord  ; DX:AX = size of file
  830.     Les BX, [BP+6]       ; ES:BX = address of NewSize&
  831.     Mov CX, ES:[BX]      ; get low byte into CX
  832.     Mov BX, ES:[BX+2]    ; get high byte in BX, BX:CX = NewSize&
  833.     Call $CmpLongInt     ; sets carry if BC:CX > DX:AX
  834.     Jnc NewSizeOK        ; if carry not set, NewSize is <= file size
  835.     Mov CX, AX           ; otherwise, substitute file size for NewSize&
  836.     Mov BX, DX           ; now BX:CX = file size
  837. NewSizeOK:
  838.     Mov DX, CX
  839.     Mov CX, BX           ; now CX:DX = byte to clip to (zero-based)
  840.     Les BX, [BP+10]      ; ES:BX = address of Handle%
  841.     Mov BX, ES:[BX]      ; BX = Handle%
  842.     Mov AX, 4200h
  843.     Int 21h              ; sets pointer to CX:DX in handle BX file
  844.     Call $CritCheck
  845.     Jc  ClipError
  846.     Xor CX, CX           ; writing zero bytes (BX = Handle%)
  847.     Mov AX, 4000h        ; DOS write to file service
  848.     Int 21h              ; clip it!
  849.     Call $CritCheck      ; any errors?
  850.     Jc  ClipError
  851. ClipExit:
  852.     Call $CritRemove
  853. BareExit:
  854.     Pop BP
  855.     Retf 8
  856. ClipError:
  857.     Mov CS:Error, AX        ; save the error code
  858.     Jmp SHORT ClipExit
  859. ClipF ENDP
  860.  
  861.  
  862. comment |************************************************************
  863. *
  864. *   Name:               KillF
  865. *
  866. *   Type:               SUB
  867. *   Parameters:         FileName$    (access at [BP+6])
  868. *   Values returned:    none
  869. *
  870. *********************************************************************|
  871.  
  872. KillF PROC FAR
  873.     Push BP
  874.     Mov BP, SP
  875.     Push DS
  876.     Push SI
  877.     Push DI
  878.     Call $CritInstall
  879.     Les BX, [BP+6]       ; load address of FileName$'s string-handle
  880.     Mov AX, ES:[BX]      ;AX = handle
  881.     Push AX
  882.     Call GETSTRLOC       ; returns address in DX:AX, length in CX
  883.     Jcxz KillBadName     ; oops! no name for the file to kill
  884.     Cmp CX, 64           ; check to see if FileName$ + CHR$(0) <= 65
  885.     Ja  KillBadName      ; if not, we can't process it
  886.     Mov DS, DX
  887.     Mov SI, AX           ;DS:SI point to first byte of Filename$
  888.     Mov AX, CS
  889.     Mov ES, AX           ;point ES at code seg
  890.     Mov DI, Offset CS:StrData ;ES:DI point to StrData
  891.     Mov DX, DI           ; DX points to StrData (for Int call later)
  892.     Rep Movsb            ; puts copy of name in StrData
  893.     Mov [DI], CL         ; puts zero char at end of filename
  894.     Mov DS, AX           ; DS:DX point to ASCIIZ filename in StrData
  895.     Mov AH, 41h          ; prepare to call DOS delete file function
  896.     Int 21h
  897.     Call $CritCheck
  898.     Jc  KillError        ; if carry set, there was an error
  899. KillExit:
  900.     Call $CritRemove
  901.     Pop DI               ; do the rest of the clean-up
  902.     Pop SI
  903.     Pop DS
  904.     Pop BP
  905.     Retf 4
  906. KillBadName:
  907.     Mov AX, 2            ; error code for "file not found"
  908. KillError:
  909.     Mov CS:Error, AX     ; put error code into Error
  910.     Jmp SHORT KillExit
  911. KillF ENDP
  912.  
  913.  
  914. comment |************************************************************
  915. *
  916. *   Name:               GetLineF
  917. *
  918. *   Type:               FUNCTION
  919. *   Parameters:         Handle%    (access at [BP+6])
  920. *   Values returned:    one line of text from: Handle%
  921. *
  922. *********************************************************************|
  923.  
  924. GetLineF PROC FAR
  925.     Push BP
  926.     Mov BP, SP
  927.     Push DS
  928.     Push DI
  929.     Push SI
  930.     Les BX, [BP+6]         ; ES:BX = Handle% address
  931.     Mov BX, ES:[BX]        ;BX = Handle% value
  932.     Cmp BX, 5              ; check if Handle% is a DOS reserved handle
  933.     Jb  BadHandle          ; if so, just return AX = null string
  934.     Cmp BX, CS:LineHandle  ;is this file handle one we're already reading?
  935.     Je  OldHandle
  936.     Jmp NewHandle          ;if it's a new handle, go initialize buffer, etc.
  937. OldHandle:
  938.     Cmp CS:LineError, 0    ;if last attempt to read resulted in an error
  939.     Jne ResumeAfterError   ;then go try to pick up where we left off
  940. Initialized:
  941.     Mov AX, CS:BufSeg
  942.     Mov DS, AX             ; DS does NOT point to the data segment now
  943.     Mov ES, AX             ; point ES at buffer, too
  944.     Mov DI, CS:BufIndex    ;ES:DI point to starting byte of next scan
  945.     Mov CX, CS:BufFilled   ;CX = total bytes read into the buffer
  946.     Add CX, CS:BufOfs
  947.     Sub CX, DI             ;CX = bytes left to scan in buffer
  948.     Cmp CX, 256            ; are there more than 256 bytes left to scan?
  949.     Jb  NearBufEnd         ; if so, stop and refill the buffer, if necessary
  950.     Mov CX, 256            ; don't scan more than 256 bytes at a time
  951. NearFileEnd:
  952.     Mov DX, CX             ; save the initial value of CX in DX (for later)
  953.     Xor BX, BX             ; assume no carriage return will be found
  954.     Mov AL, 13             ;scan for a carriage return char - CHR$(13)
  955.     Repne Scasb            ;repeat CX times or until there's a match
  956.     Jnz NoCRFound          ;if NO CHR$(13), zero flag is clear (and CX=0)
  957.     Sub DX, CX             ;subtract bytes beyond CHR$(13) from bytes scanned
  958.     Dec DX                 ;DX = num of bytes from BufIndex to first CHR$(13)
  959.     Mov BX, 2              ; adjusts BufIndex for one CR/LF pair
  960. NoCRFound:
  961.     Call $StringFill       ; this routine creates return string
  962.     Add DX, BX             ; BX = either 0 or 2, depending if CR found
  963.     Add CS:BufIndex, DX    ; BufIndex points to char to start next scan with
  964.     Mov CX, CS:BufFilled   ; calculate if we're at the last byte or none
  965.     Sub CX, CS:BufIndex
  966.     Add CX, CS:BufOfs
  967.     Jcxz SetEOF
  968.     Add CS:LinePtrLow, DX
  969.     Adc CS:LinePtrHigh, 0
  970. BufExit:
  971.     Mov AX, CS:ReturnHandle  ;return the handle of Return$
  972.     Pop SI
  973.     Pop DI
  974.     Pop DS
  975.     Pop BP
  976.     Retf 4
  977. BadHandle:
  978.     Mov CS:Error, 6        ; record an "invalid handle" error
  979. WasError:                  ; jumps here whenever an error occurs
  980.     Mov CS:ReturnHandle, 0 ; return a null string
  981.     Mov CS:LineError, 1    ; flag that an error interupted processing
  982.     Jmp SHORT BufExit      ; now we can exit the procedure
  983. ResumeAfterError:
  984.     Call $ResetLinePtr     ; after an error, try to reset DOS pointer
  985. NewHandle:
  986.     Call $InitHandle       ; initialize a new buffer & internal variables
  987.     Jc  WasError           ; if carry set, $InitHandle had an error
  988.     Mov AX, CS:BufSeg
  989.     Mov DS, AX             ; DS points to buffer segment now
  990.     Call $FillBuffer       ; fills buffer, resets BufIndex, BufFilled
  991.     Jc  WasError           ; if carry set, $FillBuffer had an error
  992.     Or  AX, AX             ; AX = bytes read into buffer
  993.     Jz  SetEOF
  994.     Jmp Initialized        ;go back to scan buffer for first return string
  995. NearBufEnd:
  996.     Cmp CS:RemainsLow, 0
  997.     Jne BufRefill          ; if RemainsLow > 0, we need to refill buffer
  998.     Cmp CS:RemainsHigh, 0  ; if low byte = 0, we need to look at the high byte
  999.     Jne BufRefill
  1000.     Jmp NearFileEnd
  1001. BufRefill:
  1002.     Add CS:RemainsLow, CX
  1003.     Adc CS:RemainsHigh, 0
  1004.     Call $FillBuffer       ; fills buffer, resets BufIndex, BufFilled
  1005.     Jc  WasError           ; if carry set, $FillBuffer had an error
  1006.     Jmp Initialized        ; jump (long) to start over with new values
  1007. SetEOF:
  1008.     Call $ReleaseMem       ;give buffer memory back to PB
  1009.     Mov CS:FileEnd, 0FFFFh      ;set the EOF marker = (-1)
  1010.     Mov CS:LineHandle, 0FFFFh   ;set file handle to impossible number (-1)
  1011.     Jmp SHORT BufExit
  1012. GetLineF ENDP
  1013.  
  1014.  
  1015. comment |************************************************************
  1016. *
  1017. *   Name:               $StringFill
  1018. *
  1019. *   Type:               internal near PROC
  1020. *   Registers altered:  AX, CX, ES, SI, DI
  1021. *
  1022. *********************************************************************|
  1023.  
  1024. $StringFill PROC NEAR      ; enter with DS=BufSeg
  1025.     Push DX                ;this push is to save DX from trashing!
  1026.     Push DX                ;DX = desired length of return string upon entry
  1027.     Call GETSTRALLOC       ; allocate a return string of that length
  1028.     Mov CS:ReturnHandle, AX ; save the handle
  1029.     Or  AX, AX             ;was it a zero?
  1030.     Jz  StrExit
  1031.     Push AX
  1032.     Call GETSTRLOC         ; now find where it is, so we can fill it
  1033.     Mov ES, DX             ; point ES:DI at it
  1034.     Mov DI, AX             ; (after allocation, CX = length of return string)
  1035.     Jcxz StrExit           ; if null, we can just exit now
  1036.     Mov SI, CS:BufIndex    ; or, let's point DS:SI at start byte of last scan
  1037.     Shr CX, 1              ; convert CX to words
  1038.     Rep Movsw              ; and copy CX words into Return$
  1039.     Jc  WriteLastByte
  1040. StrExit:
  1041.     Pop DX                 ;restore DX before continuing
  1042.     Retn
  1043. WriteLastByte:
  1044.     Inc CX
  1045.     Rep Movsb
  1046.     Jmp SHORT StrExit
  1047. $StringFill ENDP
  1048.  
  1049.  
  1050. comment |************************************************************
  1051. *
  1052. *   Name:               $ResetLinePtr
  1053. *
  1054. *   Type:               internal near PROC
  1055. *   Registers altered:  AX, BX, CX, DX, ES
  1056. *
  1057. *********************************************************************|
  1058.  
  1059. $ResetLinePtr PROC NEAR
  1060.     Call $CritInstall
  1061.     Mov DX, CS:LinePtrLow
  1062.     Mov CX, CS:LinePtrHigh
  1063.     Mov BX, CS:LineHandle
  1064.     Mov AX, 4200h
  1065.     Int 21h
  1066.     Call $CritCheck
  1067.     Jc  ResetPtrError
  1068.     Mov CS:LineError, 0
  1069. ResetPtrExit:
  1070.     Call $CritRemove
  1071.     Retn
  1072. ResetPtrError:
  1073.     Mov CS:Error, AX
  1074.     Mov CS:LineError, 1
  1075.     Jmp SHORT ResetPtrExit
  1076. $ResetLinePtr ENDP
  1077.  
  1078.  
  1079. comment |************************************************************
  1080. *
  1081. *   Name:               $FillBuffer
  1082. *
  1083. *   Type:               internal near PROC
  1084. *   Registers altered:  AX, BX, CX, DX, DI, SI
  1085. *
  1086. *********************************************************************|
  1087.  
  1088. $FillBuffer PROC NEAR      ; assumes DS = BufSeg
  1089.     Call $CritInstall
  1090.     Call $ResetLinePtr
  1091.     Mov BX, CS:LineHandle  ; we need the handle in BX for DOS call
  1092.     Mov DX, CS:BufOfs      ;point DS:DX at buffer's first byte for DOS call
  1093.     Mov CS:BufIndex, DX    ;whenever buffer is filled index reset to BufOfs
  1094.     Mov CX, CS:BufSize     ;fill the buffer with CX bytes from file
  1095.     Mov AX, 3F00h          ;request read-file service
  1096.     Int 21h                ; from DOS -- returns bytes read in AX
  1097.     Call $CritCheck
  1098.     Jc  FillBufError       ; if carry flag set, the buffer isn't filled
  1099.     Sub CS:RemainsLow, AX  ;show there are AX fewer bytes left in file
  1100.     Sbb CS:RemainsHigh, 0  ;make certain high word also reflects the subtract
  1101.     Mov CS:BufFilled, AX   ; if not, save actual BufFilled
  1102. FillBufExit:
  1103.     Call $CritRemove
  1104.     Retn
  1105. FillBufError:
  1106.     Mov CS:Error, AX       ; save the error
  1107.     Jmp SHORT FillBufExit
  1108. $FillBuffer ENDP
  1109.  
  1110.  
  1111. comment |************************************************************
  1112. *
  1113. *   Name:               $ReleaseMem
  1114. *
  1115. *   Type:               internal near PROC
  1116. *   Registers altered:  AX (plus any altered by RLSSTRALLOC)
  1117. *
  1118. *********************************************************************|
  1119.  
  1120. $ReleaseMem PROC NEAR
  1121.     Mov AX, CS:BufHandle
  1122.     Push AX
  1123.     Call RLSSTRALLOC       ; try to release the current buffer back to PB
  1124.     Or  AX, AX             ; when AX <> 0, the string was released
  1125.     Jz  NotReleased        ; if we can't release it, we'll reuse it
  1126.     Mov CS:BufHandle, 0    ; reset the handle as "no handle allocated"
  1127. NotReleased:
  1128.     Retn
  1129. $ReleaseMem ENDP
  1130.  
  1131.  
  1132. comment |************************************************************
  1133. *
  1134. *   Name:               $InitHandle
  1135. *
  1136. *   Type:               internal near PROC
  1137. *   Registers altered:  AX, BX, CX, DX, ES
  1138. *
  1139. *********************************************************************|
  1140.  
  1141. $InitHandle PROC NEAR
  1142.     Mov CS:LineHandle, BX  ; save this file handle as current handle
  1143.     Mov CS:FileEnd, 0      ; zero this variable when there's a new file
  1144.     Call $CritInstall      ; this trashes BX
  1145.     Mov BX, CS:LineHandle  ; so resore it back to file handle
  1146.     Xor DX, DX
  1147.     Xor CX, CX           ; tell DOS we'll be moving zero bytes
  1148.     Mov AX, 4201h        ; from the present file position
  1149.     Int 21h
  1150.     Call $CritCheck
  1151.     Jc  InitError
  1152.     Mov CS:LinePtrLow, AX
  1153.     Mov CS:LinePtrHigh, DX
  1154.     Push AX                ; save 'em on the stack, too
  1155.     Push DX
  1156.     Mov AX, Offset CS:LineHandle
  1157.     Push CS                ; push seg:off address of CS:LineHandle
  1158.     Push AX
  1159.     Call FAR PTR SizeF
  1160.     Jc  InitExit           ; error code already saved, just exit
  1161.     Pop BX
  1162.     Pop CX                 ; BX:CX = ptr location in file
  1163.     Sub AX, CX
  1164.     Sbb DX, BX             ; DX:AX = bytes remaining from ptr to end
  1165.     Mov CS:RemainsLow, AX  ; save that value in RemainsHigh:RemainsLow
  1166.     Mov CS:RemainsHigh, DX
  1167.     Mov AX, CS:BufHandle   ; do we already have a buffer allocated?
  1168.     Or  AX, AX             ; if so, it was because we couldn't release it!
  1169.     Jnz UsePrevBuffer      ; so we'll just go ahead and reuse it
  1170.     Mov BX, CS:BufSize     ;BX = length of buffer in bytes
  1171.     Push BX                ; push bytes requested for GETSTRALLOC
  1172.     Call GETSTRALLOC       ; allocate a buffer string
  1173.     Or  AX, AX             ; see if the allocation worked (if not, AX=0)
  1174.     Jz  NoBuffer           ; if there's no buffer string, bail out now
  1175.     Mov CS:BufHandle, AX   ; save the string handle for later release
  1176. UsePrevBuffer:
  1177.     Push AX                ; push string handle for GETSTRLOC
  1178.     Call GETSTRLOC         ; find our string/buffer
  1179.     Mov CS:BufSeg, DX      ; nail down the Seg:Ofs address
  1180.     Mov CS:BufOfs, AX
  1181.     Mov CS:BufIndex, AX    ; point index at first byte of buffer, too
  1182.     Mov CS:BufFilled, CX   ; assume all the buffer will be used, adjust later
  1183.     Mov CS:BufSize, CX     ; save buffer size, in case using prev buffer
  1184. InitExit:
  1185.     Call $CritRemove
  1186.     Retn
  1187. InitError:
  1188.     Mov CS:Error, AX       ; save the error
  1189.     Jmp SHORT InitExit     ; carry flag already set
  1190. NoBuffer:
  1191.     Mov CS:Error, -1       ; let AX = -1 when string allocation fails
  1192.     Stc                    ; set the carry flag to flag the error
  1193.     Jmp SHORT InitExit     ; and return -1 as the "error number"
  1194. $InitHandle ENDP
  1195.  
  1196.  
  1197. comment |************************************************************
  1198. *
  1199. *   Name:               $CmpLngInt
  1200. *
  1201. *   Type:               internal near PROC
  1202. *   Registers altered:  flags register
  1203. *
  1204. *********************************************************************|
  1205.  
  1206. $CmpLongInt PROC NEAR
  1207.     Cmp BX, DX        ; begin to compare DX:AX to BX:CX
  1208.     Jg  BXCXMore      ; if BX > DX then BX:CX > DX:AX
  1209.     Cmp DX, BX        ; see if DX > BX
  1210.     Jg  BXCXNotMore   ; if DX = BX this falls through to next compare
  1211.     Cmp AX, CX        ; compare low words, using unsigned comparison
  1212.     Jb  BXCXMore      ; if AX < CX then BX:CX is greater
  1213. BXCXNotMore:
  1214.     Clc               ; clear carry when BX:CX <= DX:AX
  1215. CmpExit:
  1216.     Retn              ; and return
  1217. BXCXMore:
  1218.     Stc               ; set carry when BX:CX > DX:AX
  1219.     Jmp SHORT CmpExit
  1220. $CmpLongInt ENDP
  1221.  
  1222.  
  1223. comment |************************************************************
  1224. *
  1225. *   Name:               $CritInstall
  1226. *
  1227. *   Type:               internal near PROC
  1228. *   Registers altered:  AX, BX, DX, ES
  1229. *
  1230. *********************************************************************|
  1231.  
  1232. $CritInstall PROC NEAR
  1233.     Push DS                 ; DON'T trash DS!
  1234.     Mov CS:CritErrCode, 0   ; make sure CritErrCode is zeroed out
  1235.     Mov AX, 3524h           ; call DOS service to return current
  1236.     Int 21h                 ; interrupt vector
  1237.     Mov CS:Old24Offset, BX  ; save that vector for later
  1238.     Mov CS:Old24Segment, ES
  1239.     Push CS
  1240.     Pop DS                  ; point DS:DX at new interrupt handler
  1241.     Mov DX, Offset $CritHandler
  1242.     Mov AX, 2524h           ; call DOS service to set new vector
  1243.     Int 21h                 ; all set (DOS returns no values here)
  1244.     Pop DS                  ; so restore everything we tampered with
  1245.     Retn
  1246. $CritInstall ENDP
  1247.  
  1248.  
  1249. comment |************************************************************
  1250. *
  1251. *   Name:               $CritHandler
  1252. *
  1253. *   Type:               internal near PROC
  1254. *   Registers altered:  AL
  1255. *
  1256. *********************************************************************|
  1257.  
  1258. $CritHandler PROC FAR
  1259.     Push AX                 ; do as little damage as possible
  1260.     Mov AX, DI              ; when handler called, error code in DI
  1261.     Inc AX                  ; must show something is there if code=0
  1262.     Mov CS:CritErrCode, AX  ; store it in memory for later retrieval
  1263.     Pop AX                  ; this ensures AH is preserved
  1264.     Xor AL, AL              ; returning zero in AL instructs DOS to
  1265.     Iret                    ; ignore the error
  1266. $CritHandler ENDP
  1267.  
  1268.  
  1269. comment |************************************************************
  1270. *
  1271. *   Name:               $CritCheck
  1272. *
  1273. *   Type:               internal near PROC
  1274. *   Registers altered:  AX (only if error code detected)
  1275. *
  1276. *********************************************************************|
  1277.  
  1278. $CritCheck PROC NEAR        ; trashes nothing, returns error code in AX
  1279.     PushF                   ; the flags will change during this proc
  1280.     Cmp CS:CritErrCode, 0   ; look for an error
  1281.     Jne IsCritError
  1282.     PopF                    ; restore flags and go
  1283. CritError:
  1284.     Retn
  1285. IsCritError:
  1286.     Mov AX, CS:CritErrCode  ; return error in AX
  1287.     Add AX, 18              ; make it a standard error code
  1288.     PopF                    ; restore all flags, before setting carry flag
  1289.     Stc                     ; flag a live one with carry
  1290.     Jmp SHORT CritError
  1291. $CritCheck ENDP
  1292.  
  1293.  
  1294. comment |************************************************************
  1295. *
  1296. *   Name:               $CritRemove
  1297. *
  1298. *   Type:               internal near PROC
  1299. *   Registers altered:  none
  1300. *
  1301. *********************************************************************|
  1302.  
  1303. $CritRemove PROC NEAR
  1304.     Push DS
  1305.     Push DX                 ; don't trash DX:AX!! IMPORTANT
  1306.     Push AX
  1307.     PushF                   ; preserve flags register
  1308.     Mov AX, CS:Old24Segment
  1309.     Mov DS, AX              ; point DS:DX at old interrupt handler
  1310.     Mov DX, CS:Old24Offset
  1311.     Mov AX, 2524h           ; call DOS service to set the vector
  1312.     Int 21h                 ; all set / DOS returns no values here
  1313.     PopF
  1314.     Pop AX
  1315.     Pop DX
  1316.     Pop DS
  1317.     Retn
  1318. $CritRemove ENDP
  1319.  
  1320. Code ENDS
  1321.      END
  1322.